package com.qdlc.p2p.biz.tpp.model;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qdlc.p2p.biz.service.PayService;
import com.qdlc.p2p.biz.util.SinaCallServiceUtil;
import com.qdlc.p2p.common.constant.Constant;
import com.qdlc.p2p.common.constant.SinaConstant;
import com.qdlc.p2p.common.exception.UserException;
import com.qdlc.p2p.common.util.BeanUtil;
import com.qdlc.p2p.common.util.ReflectUtil;
import com.qdlc.p2p.common.util.SinaGsonUtil;
import com.qdlc.p2p.common.util.SinaSignUtil;
import com.qdlc.p2p.common.util.SinaTools;
import com.qdlc.p2p.common.util.StringUtil;
import com.qdlc.p2p.common.util.TppPropertyUtil;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.dto.Pay;

/**
 * 
 * 新浪支付
 * @author zlhx
 * @version 2.0
 * @date 2015年8月8日 下午4:52:26
 */
public class SinaModel {
    private static final Logger logger = Logger.getLogger(SinaModel.class);
	/**
	 * 接口版本
	 * 类型（长度）：Number(5)
	 */
	private String version = "1.0";
	
	/**
	 * 接口名称
	 * 类型（长度）：String(64)
	 */
	private String service;
	
	/**
	 * 请求时间 格式yyyyMMddhhmmss
	 * 类型（长度）：String(14)
	 */
	private String request_time;
	
	/**
	 * 合作者身份ID
	 * 签约合作方的钱包唯一用户号
	 * 类型（长度）：String(32)
	 */
	private String partner_id;
	
	/**
	 * 参数编码字符集
	 * 类型（长度）：String(10)
	 */
	private String _input_charset="UTF-8";
	
	/**
	 * 签名
	 * 类型（长度）：String(256)
	 */
	private String sign;
	/**
	 * 签名字符串，用于页面显示
	 */
	private String signStr;
	
	/**
	 * 签名方式 MD5/RSA  建议MD5
	 * 类型（长度）：String(10)
	 */
	private String sign_type = "RSA";
	
	/**
	 * 签名版本号 默认1.0
	 * 类型（长度）：Number(5)
	 */
	private String sign_version = "1.0";
	
	/**
	 * 加密版本号 默认1.0
	 * 类型（长度）：Number(5)
	 */
	private String encrypt_version = "1.0";
	
	/**
	 * 标识信息 (用户Id,可以用UUID代替)
	 * 类型（长度）：String(32)
	 */
	private String identity_id;
	
	/**
	 * 标识类型 
	 * 类型（长度）：String(32)
	 */
	private String identity_type;
	
	/**
	 * 异步回调地址  （响应结果为“success”）
	 * 类型（长度）：String(1000)
	 */
	private String notify_url;
	
	/**
	 * 同步回调地址
	 * 类型（长度）：String(1000)
	 */
	private String return_url;
	
	/**
	 * 备注
	 * 类型（长度）：String(1000)
	 */
	private String memo;

	/**
	 * url 类型  1：资金类  0 会员类
	 */
	private int url_type;
	
	/**
	 * 会员类提交路径
	 */
	private String member_url;
	
	/**
	 * 资金类提交路径
	 */
	private String cash_url;
	
	/**
	 * 响应时间 格式yyyyMMddhhmmss
	 * 类型（长度）：String(14)
	 */
	private String response_time;
	
	/**
	 * 响应码
	 * 类型（长度）：String(30)
	 */
	private String response_code;
	
	/**
	 * 响应信息
	 * 类型（长度）：String(200)
	 */
	private String response_message;
	/**
	 * 待签名字符数组
	 */
	private String[] signParamNames=new String[]{};
	
	/**
	 * 提交签名字符数组
	 */
	private String[] subParamNames = new String[]{};
	
	/**
	 * map集合 签名 排序时使用 
	 */
	private Map<String, String> data;
	
	/**
	 * 验签密钥
	 */
	private String signKey;
	
	/**
	 * 是否需要urlEncode 
	 */
	private boolean encode;
	
	/**
	 * RSA公钥
	 */
	private String rsaPublic;
	
	/**
	 * 电子邮件
	 */
	private String memberEmail;
	
	/**
	 * 扩展信息 参数名1^参数值1|参数名2^参数值2|.. 
	 */
	private String extend_param;
	
	public SinaModel() {
		super();
		init();
	}

	public void init(){
		
		PayService payService = (PayService) BeanUtil.getBean("payService");
        //Pay pay = payService.findByNid(Constant.SINA);
		Pay pay = payService.findByNid("sina");
        if (pay != null) {
        	
        	if("1".equals(SystemConfigHelper.getValue(Nid.CONFIG_ONLINE))){//开通线上配置环境环境
        		setPartner_id(SystemConfigHelper.getValue(Nid.MERCHANT_ID));
        		setSignKey(SystemConfigHelper.getValue(Nid.RAS_PUBLIC_KEY));
    			setMember_url(SystemConfigHelper.getValue(Nid.REQUEST_URL));
    			setCash_url(SystemConfigHelper.getValue(Nid.RETURN_URL));
    			setMemberEmail(SystemConfigHelper.getValue(Nid.MEMBER_EMAIL));
    			setRsaPublic(SystemConfigHelper.getValue(Nid.CHECK_SIGN_KEY));
    		}else{//开通测试环境地址
    			setPartner_id(TppPropertyUtil.getMessage("tpp_merid"));
        		setSignKey(TppPropertyUtil.getMessage("tpp_rsa_public"));
    			setMember_url(TppPropertyUtil.getMessage("tpp_test_memeber_url"));
    			setCash_url(TppPropertyUtil.getMessage("tpp_test_cash_url"));
    			setMemberEmail(TppPropertyUtil.getMessage("tpp_member_email"));
    			setRsaPublic(TppPropertyUtil.getMessage("tpp_rsa_public"));
    		}
        } else {
        	// 默认测试环境
        	setPartner_id(TppPropertyUtil.getMessage("tpp_merid"));
    		setSignKey(TppPropertyUtil.getMessage("tpp_sign_key"));
			setMember_url(TppPropertyUtil.getMessage("tpp_test_memeber_url"));
			setCash_url(TppPropertyUtil.getMessage("tpp_test_cash_url"));
			setMemberEmail(TppPropertyUtil.getMessage("tpp_member_email"));
			setRsaPublic(TppPropertyUtil.getMessage("tpp_rsa_public"));
        }
	}
	
	/**
	 * 拓展信息解析
	 * @param map
	 * @return
	 * @param
	 */
	public void setExtendParam(Map<String, Object> map){
		StringBuffer sb = new StringBuffer(50);
		int i = 0;
		for (Map.Entry<String, Object> entry: map.entrySet()) {
			if (i > 0) sb.append("|");
			sb.append(entry.getKey()).append("^").append(entry.getValue());
			i++;
		}
		extend_param = sb.toString();
	}
	
	
	/**
	 * 动态创建参数map
	 * @return
	 * @param
	 */
	public Map<String,String> getMapData(String[] paramNames){
		data = new HashMap<String, String>();
		for (String string : paramNames) {
			Object result=ReflectUtil.invokeGetMethod(getClass(), this, string);
			String value=(result==null?"":result.toString());
			data.put(string, value);
		}
		return data;
	}
	
	/**
	 * 封装回调响应参数
	 * 
	 * @param res
	 * @return
	 * @throws IOException
	 */
	public SinaModel response(String res) throws IOException {
		try {
			JSONObject json = JSON.parseObject(res);
			response_code = json.getString("response_code");
			response_message = json.getString("response_message");
			memo = json.getString("memo");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 签名
	 * @return
	 * @throws Exception
	 */
	public String sign(String[] paramNames) throws Exception{
		getMapData(paramNames);
		if(data == null) return null;
		String signStr = SinaTools.createLinkString(data, false);
		String sign = SinaSignUtil.sign(signStr, sign_type, signKey, _input_charset);
		return sign;
	}
	
	
	/**
	 * 提交方法
	 * @return
	 * @param
	 * @throws Exception 
	 */
	public String submit() throws Exception{
		//验签
		this.sign = sign(getSignParamNames());

		//封装提交参数
		String param = SinaTools.createLinkString(getMapData(getSubParamNames()), isEncode());
		logger.info("封装提交参数param============="+param+"==================sign==========="+sign);

		//实时获取提交后返回结果
		String result = URLDecoder.decode(SinaCallServiceUtil.sendPost(getUrl(), param), get_input_charset());
		logger.info("实时获取提交后返回结果==============" + result);
        logger.debug("实时获取提交后返回结果==============" + result);

		//解析返回结果
		Map<String, String> content = SinaGsonUtil.fronJson2Map(result);
		
		//取响应码，如果不是成功则抛出异常
		this.response_code = content.get("response_code");
		this.response_message = content.get("response_message");
		if(!SinaConstant.RESPONSE_CODE_SUCCESS.equals(response_code)){
			throw new UserException("新浪提交异常：" + response_message);
		}
		if (StringUtil.isNotBlank(result)) {
			this.response(result);
		}
		
		
		return result;
	}
	
	/**
	 * 获取Url
	 * @return
	 * @param
	 */
	public String getUrl(){
		switch (this.url_type) {
		case 1:
			return getCash_url();
		default:
			return getMember_url();
		}
	}
	
	
	//------------------get/set---------------
	/**
	 * 获取 接口版本
	 * 类型（长度）：Number(5)
	 * @return 
	 */
	public String getVersion() {
		return version;
	}

	/**
	 * 设置 接口版本
	 * 类型（长度）：Number(5)
	 * @param 
	 */
	public void setVersion(String version) {
		this.version = version;
	}

	/**
	 * 获取 接口名称
	 * 类型（长度）：String(64)
	 * @return 
	 */
	public String getService() {
		return service;
	}

	/**
	 * 设置 接口名称
	 * 类型（长度）：String(64)
	 * @param 
	 */
	public void setService(String service) {
		this.service = service;
	}

	/**
	 * 获取 请求时间 格式yyyyMMddhhmmss 
	 * 类型（长度）：String(14)
	 * @return 
	 */
	public String getRequest_time() {
		return request_time;
	}

	/**
	 * 设置 请求时间 格式yyyyMMddhhmmss 
	 * 类型（长度）：String(14)
	 * @param 
	 */
	public void setRequest_time(String request_time) {
		this.request_time = request_time;
	}

	/**
	 * 获取 合作者身份ID 签约合作方的钱包唯一用户号 
	 * 类型（长度）：String(32)
	 * @return 
	 */
	public String getPartner_id() {
		return partner_id;
	}

	/**
	 * 设置 合作者身份ID 签约合作方的钱包唯一用户号 
	 * 类型（长度）：String(32)
	 * @param 
	 */
	public void setPartner_id(String partner_id) {
		this.partner_id = partner_id;
	}

	/**
	 * 获取 参数编码字符集 
	 * 类型（长度）：String(10)
	 * @return 
	 */
	public String get_input_charset() {
		return _input_charset;
	}

	/**
	 * 设置 参数编码字符集 
	 * 类型（长度）：String(10)
	 * @param 
	 */
	public void set_input_charset(String _input_charset) {
		this._input_charset = _input_charset;
	}

	/**
	 * 获取 签名 
	 * 类型（长度）：String(256)
	 * @return 
	 */
	public String getSign() {
		return sign;
	}

	/**
	 * 设置  签名 
	 * 类型（长度）：String(256)
	 * @param 
	 */
	public void setSign(String sign) {
		this.sign = sign;
	}

	/**
	 * 获取 签名方式 MD5/RSA 建议MD5 
	 * 类型（长度）：String(10)
	 * @return 
	 */
	public String getSign_type() {
		return sign_type;
	}

	/**
	 * 设置 签名方式 MD5/RSA 建议MD5 
	 * 类型（长度）：String(10)
	 * @param 
	 */
	public void setSign_type(String sign_type) {
		this.sign_type = sign_type;
	}

	/**
	 * 获取 签名版本号 默认1.0 
	 * 类型（长度）：Number(5)
	 * @return 
	 */
	public String getSign_version() {
		return sign_version;
	}

	/**
	 * 设置 签名版本号 默认1.0 
	 * 类型（长度）：Number(5)
	 * @param 
	 */
	public void setSign_version(String sign_version) {
		this.sign_version = sign_version;
	}

	/**
	 * 获取 加密版本号 默认1.0 
	 * 类型（长度）：Number(5)
	 * @return 
	 */
	public String getEncrypt_version() {
		return encrypt_version;
	}

	/**
	 * 设置 加密版本号 默认1.0 
	 * 类型（长度）：Number(5)
	 * @param 
	 */
	public void setEncrypt_version(String encrypt_version) {
		this.encrypt_version = encrypt_version;
	}
	
	/**
	 * 获取 标识信息
	 * @return 
	 */
	public String getIdentity_id() {
		return identity_id;
	}
	
	/**
	 * 设置 标识信息
	 * @param 
	 */
	public void setIdentity_id(String identity_id) {
		this.identity_id = identity_id;
	}
	
	/**
	 * 获取 标识类型
	 * @return 
	 */
	public String getIdentity_type() {
		return identity_type;
	}
	
	/**
	 * 设置 标识类型
	 * @param 
	 */
	public void setIdentity_type(String identity_type) {
		this.identity_type = identity_type;
	}
	

	/**
	 * 获取 异步回调地址 （响应结果为“success”） 
	 * 类型（长度）：String(1000)
	 * @return 
	 */
	public String getNotify_url() {
		return notify_url;
	}

	/**
	 * 设置 异步回调地址 （响应结果为“success”） 
	 * 类型（长度）：String(1000)
	 * @param 
	 */
	public void setNotify_url(String notify_url) {
		this.notify_url = notify_url;
	}

	/**
	 * 获取 同步回调地址
	 * 类型（长度）：String(1000)
	 * @return 
	 */
	public String getReturn_url() {
		return return_url;
	}

	/**
	 * 设置 同步回调地址
	 * 类型（长度）：String(1000)
	 * @param 
	 */
	public void setReturn_url(String return_url) {
		this.return_url = return_url;
	}

	/**
	 * 获取 备注 
	 * 类型（长度）：String(1000)
	 * @return 
	 */
	public String getMemo() {
		return memo;
	}

	/**
	 * 设置 备注 
	 * 类型（长度）：String(1000)
	 * @param 
	 */
	public void setMemo(String memo) {
		this.memo = memo;
	}

	/**
	 * 获取 会员类提交路径
	 * @return 
	 */
	public String getMember_url() {
		return member_url;
	}

	/**
	 * 设置 会员类提交路径
	 * @param 
	 */
	public void setMember_url(String member_url) {
		this.member_url = member_url;
	}

	/**
	 * 获取 资金类提交路径
	 * @return 
	 */
	public String getCash_url() {
		return cash_url;
	}

	/**
	 * 设置 资金类提交路径
	 * @param 
	 */
	public void setCash_url(String cash_url) {
		this.cash_url = cash_url;
	}

	/**
	 * 获取 响应时间 格式yyyyMMddhhmmss 
	 * 类型（长度）：String(14)
	 * @return 
	 */
	public String getResponse_time() {
		return response_time;
	}

	/**
	 * 设置  响应时间 格式yyyyMMddhhmmss 
	 * 类型（长度）：String(14)
	 * @param 
	 */
	public void setResponse_time(String response_time) {
		this.response_time = response_time;
	}

	/**
	 * 获取 响应码 
	 * 类型（长度）：String(30)
	 * @return 
	 */
	public String getResponse_code() {
		return response_code;
	}

	/**
	 * 设置 响应码 
	 * 类型（长度）：String(30)
	 * @param 
	 */
	public void setResponse_code(String response_code) {
		this.response_code = response_code;
	}

	/**
	 * 获取 响应信息 
	 * 类型（长度）：String(200)
	 * @return 
	 */
	public String getResponse_message() {
		return response_message;
	}

	/**
	 * 设置 响应信息 
	 * 类型（长度）：String(200)
	 * @param 
	 */
	public void setResponse_message(String response_message) {
		this.response_message = response_message;
	}

	/**
	 * 获取  待签名字符数组
	 * @return 
	 */
	public String[] getSignParamNames() {
		return signParamNames;
	}

	/**
	 * 设置 待签名字符数组
	 * @param 
	 */
	public void setSignParamNames(String[] signParamNames) {
		this.signParamNames = signParamNames;
	}

	/**
	 * 获取 提交签名字符数组
	 * @return 
	 */
	public String[] getSubParamNames() {
		return subParamNames;
	}

	/**
	 * 设置 提交签名字符数组
	 * @param 
	 */
	public void setSubParamNames(String[] subParamNames) {
		this.subParamNames = subParamNames;
	}

	/**
	 * 获取 map集合 签名 排序时使用 
	 * @return 
	 */
	public Map<String, String> getData() {
		return data;
	}

	/**
	 * 设置 map集合 签名 排序时使用 
	 * @param 
	 */
	public void setData(Map<String, String> data) {
		this.data = data;
	}

	/**
	 * 获取 是否需要urlEncode 
	 * @return 
	 */
	public boolean isEncode() {
		return encode;
	}

	/**
	 * 设置 是否需要urlEncode 
	 * @param 
	 */
	public void setEncode(boolean encode) {
		this.encode = encode;
	}

	/**
	 * 获取 md5验签字符串
	 * @return 
	 */
	public String getSignKey() {
		return signKey;
	}

	/**
	 * 设置 md5验签字符串
	 * @param 
	 */
	public void setSignKey(String signKey) {
		this.signKey = signKey;
	}

	/**
	 * 获取 签名字符串，用于页面显示
	 * @return 
	 */
	public String getSignStr() {
		return signStr;
	}

	/**
	 * 设置 签名字符串，用于页面显示
	 * @param 
	 */
	public void setSignStr(String signStr) {
		this.signStr = signStr;
	}
	
	/**
	 * 获取 扩展信息 参数名1^参数值1|参数名2^参数值2|.. 
	 * 类型(长度)：String(200)
	 * @return 
	 */
	public String getExtend_param() {
		return extend_param;
	}

	/**
	 * 设置 扩展信息 参数名1^参数值1|参数名2^参数值2|.. 
	 * 类型(长度)：String(200)
	 * @param 
	 */
	public void setExtend_param(String extend_param) {
		this.extend_param = extend_param;
	}

	/**
	 * 获取 url 类型 1：资金类 0 会员类
	 * @return 
	 */
	public int getUrl_type() {
		return url_type;
	}

	/**
	 * 设置 url 类型 1：资金类 0 会员类
	 * @param 
	 */
	public void setUrl_type(int url_type) {
		this.url_type = url_type;
	}

	/**
	 * @return rsaPublic
	 */
	public String getRsaPublic() {
		return rsaPublic;
	}

	/**
	 * @param rsaPublic 要设置的 rsaPublic
	 */
	public void setRsaPublic(String rsaPublic) {
		this.rsaPublic = rsaPublic;
	}

	/**
	 * @return memberEmail
	 */
	public String getMemberEmail() {
		return memberEmail;
	}

	/**
	 * @param memberEmail 要设置的 memberEmail
	 */
	public void setMemberEmail(String memberEmail) {
		this.memberEmail = memberEmail;
	}
	
	
}
